// JavaScript Document
// ---- vison_ruan@126.com ... for extends layout component
// ---- create ColumnTree ----
Ext.tree.ColumnTree = Ext.extend(Ext.tree.TreePanel, {
    lines:false,
    borderWidth: Ext.isBorderBox ? 0 : 2, // the combined left/right border for each cell
    cls:'x-column-tree',
    
    onRender : function(){
        Ext.tree.ColumnTree.superclass.onRender.apply(this, arguments);
        this.headers = this.body.createChild(
            {cls:'x-tree-headers'},this.innerCt.dom);

        var cols = this.columns, c;
        var totalWidth = 0;


        for(var i = 0, len = cols.length; i < len; i++){
             c = cols[i];
             totalWidth += c.width;
             this.headers.createChild({
                 cls:'x-tree-hd ' + (c.cls?c.cls+'-hd':''),
                 cn: {
                     cls:'x-tree-hd-text',
                     html: c.header
                 },
                 style:'width:'+(c.width-this.borderWidth)+'px;'
             });
        }
	
        this.headers.createChild({cls:'x-clear'});
	
        // prevent floats from wrapping when clipped
        this.headers.setWidth(totalWidth);
			
        this.innerCt.setWidth(totalWidth);
    }
});

Ext.tree.ColumnNodeUI = Ext.extend(Ext.tree.TreeNodeUI, {
    focus: Ext.emptyFn, // prevent odd scrolling behavior

    renderElements : function(n, a, targetNode, bulkRender){
        this.indentMarkup = n.parentNode ? n.parentNode.ui.getChildIndent() : '';

        var t = n.getOwnerTree();
        var cols = t.columns;
        var bw = t.borderWidth;
        var c = cols[0];

        var buf = [
             '<li class="x-tree-node"><div ext:tree-node-id="',n.id,'" class="x-tree-node-el x-tree-node-leaf ', a.cls,'">',
                '<div class="x-tree-col" style="width:',c.width-bw,'px;">',
                    '<span class="x-tree-node-indent">',this.indentMarkup,"</span>",
                    '<img src="', this.emptyIcon, '" class="x-tree-ec-icon x-tree-elbow">',
                    '<img src="', a.icon || this.emptyIcon, '" class="x-tree-node-icon',(a.icon ? " x-tree-node-inline-icon" : ""),(a.iconCls ? " "+a.iconCls : ""),'" unselectable="on">',
                    '<a hidefocus="on" class="x-tree-node-anchor" href="',a.href ? a.href : "#",'" tabIndex="1" ',
                    a.hrefTarget ? ' target="'+a.hrefTarget+'"' : "", '>',
                    '<span unselectable="on">', n.text || (c.renderer ? c.renderer(a[c.dataIndex], n, a) : a[c.dataIndex]),"</span></a>",
                "</div>"];
         for(var i = 1, len = cols.length; i < len; i++){
             c = cols[i];

             buf.push('<div class="x-tree-col ',(c.cls?c.cls:''),'" style="width:',c.width-bw,'px;">',
                        '<div class="x-tree-col-text">',(c.renderer ? c.renderer(a[c.dataIndex], n, a) : a[c.dataIndex]),"</div>",
                      "</div>");
         }
         buf.push(
            '<div class="x-clear"></div></div>',
            '<ul class="x-tree-node-ct" style="display:none;"></ul>',
            "</li>");

        if(bulkRender !== true && n.nextSibling && n.nextSibling.ui.getEl()){
            this.wrap = Ext.DomHelper.insertHtml("beforeBegin",
                                n.nextSibling.ui.getEl(), buf.join(""));
        }else{
            this.wrap = Ext.DomHelper.insertHtml("beforeEnd", targetNode, buf.join(""));
        }

        this.elNode = this.wrap.childNodes[0];
        this.ctNode = this.wrap.childNodes[1];

        var cs = this.elNode.firstChild.childNodes;
        this.indentNode = cs[0];

        this.ecNode = cs[1];
        this.iconNode = cs[2];
        this.anchor = cs[3];
        this.textNode = cs[3].firstChild;
    }
});

// ---- create RowExpander component ----
Ext.grid.RowExpander = function(config){
    Ext.apply(this, config);

    this.addEvents({
        beforeexpand : true,
        expand: true,
        beforecollapse: true,
        collapse: true
    });

    Ext.grid.RowExpander.superclass.constructor.call(this);

    if(this.tpl){
        if(typeof this.tpl == 'string'){
            this.tpl = new Ext.Template(this.tpl);
        }
        this.tpl.compile();
    }

    this.state = {};
    this.bodyContent = {};
};

Ext.extend(Ext.grid.RowExpander, Ext.util.Observable, {
    header: "",
    width: 20,
    sortable: false,
    fixed:true,
    dataIndex: '',
    id: 'expander',
    lazyRender : true,
    enableCaching: true,

    getRowClass : function(record, rowIndex, p, ds){
        p.cols = p.cols-1;
        var content = this.bodyContent[record.id];
        if(!content && !this.lazyRender){
            content = this.getBodyContent(record, rowIndex);
        }
        if(content){
            p.body = content;
        }
        return this.state[record.id] ? 'x-grid3-row-expanded' : 'x-grid3-row-collapsed';
    },

    init : function(grid){
        this.grid = grid;

        var view = grid.getView();
        view.getRowClass = this.getRowClass.createDelegate(this);

        view.enableRowBody = true;

        grid.on('render', function(){
            view.mainBody.on('mousedown', this.onMouseDown, this);
        }, this);
    },

    getBodyContent : function(record, index){
        if(!this.enableCaching){
            return this.tpl.apply(record.data);
        }
        var content = this.bodyContent[record.id];
        if(!content){
            content = this.tpl.apply(record.data);
            this.bodyContent[record.id] = content;
        }
        return content;
    },

    onMouseDown : function(e, t){
        if(t.className == 'x-grid3-row-expander'){
            e.stopEvent();
            var row = e.getTarget('.x-grid3-row');
            this.toggleRow(row);
        }
    },

    renderer : function(v, p, record){
        p.cellAttr = 'rowspan="2"';
        return '<div class="x-grid3-row-expander">&#160;</div>';
    },

    beforeExpand : function(record, body, rowIndex){
        if(this.fireEvent('beforeexpand', this, record, body, rowIndex) !== false){
            if(this.tpl && this.lazyRender){
                body.innerHTML = this.getBodyContent(record, rowIndex);
            }
            return true;
        }else{
            return false;
        }
    },

    toggleRow : function(row){
        if(typeof row == 'number'){
            row = this.grid.view.getRow(row);
        }
        this[Ext.fly(row).hasClass('x-grid3-row-collapsed') ? 'expandRow' : 'collapseRow'](row);
    },

    expandRow : function(row){
        if(typeof row == 'number'){
            row = this.grid.view.getRow(row);
        }
        var record = this.grid.store.getAt(row.rowIndex);
        var body = Ext.DomQuery.selectNode('tr:nth(2) div.x-grid3-row-body', row);
        if(this.beforeExpand(record, body, row.rowIndex)){
            this.state[record.id] = true;
            Ext.fly(row).replaceClass('x-grid3-row-collapsed', 'x-grid3-row-expanded');
            this.fireEvent('expand', this, record, body, row.rowIndex);
        }
    },

    collapseRow : function(row){
        if(typeof row == 'number'){
            row = this.grid.view.getRow(row);
        }
        var record = this.grid.store.getAt(row.rowIndex);
        var body = Ext.fly(row).child('tr:nth(1) div.x-grid3-row-body', true);
        if(this.fireEvent('beforcollapse', this, record, body, row.rowIndex) !== false){
            this.state[record.id] = false;
            Ext.fly(row).replaceClass('x-grid3-row-expanded', 'x-grid3-row-collapsed');
            this.fireEvent('collapse', this, record, body, row.rowIndex);
        }
    }
});

Ext.ux.SubTableRowExpander = function(config){
	if (!config.subdata) { 
		config.subdata = 'subdata';
	}
    Ext.apply(this, config);

    Ext.ux.SubTableRowExpander.superclass.constructor.call(this);

    this.state = {};
    this.bodyContent = {};
	
};


Ext.extend(Ext.ux.SubTableRowExpander, Ext.grid.RowExpander, {
	enableCaching: false,
	
	init: function (grid) {
		
		 this.addEvents({
        	dblclick: true,
			mouseover: true,
			mouseout: true,
			subdblclick: true
			});

	    var ret = Ext.ux.SubTableRowExpander.superclass.init.call(this, grid);
		
		this.grid.view.afterMethod('onColumnHiddenUpdated', this.reconfigureTemplate, this);
		this.grid.view.afterMethod('onLayout', this.reconfigureTemplate, this);
		this.grid.view.afterMethod('onColumnWidthUpdated', this.doWidth, this);
		this.grid.view.afterMethod('onAllColumnWidthsUpdated', this.doAllWidths, this);
		this.grid.view.afterMethod('afterMove', this.doAllWidths, this);
		
		this.grid.on('dblclick', this.onDblClick, this);
		
		this.grid.store.on('load', function (store, records) { this.createSubdata(); }.createDelegate(this));
		this.createSubdata();
		
		this.on("expand", function (e, record) {
			var res = Ext.query("table.x-grid3-row-subtable");

			
			for (var i=0;i<res.length;i++) {
				
				Ext.fly(res[i]).on("mouseover", this.onMouseOver);
				Ext.fly(res[i]).on("mouseout", this.onMouseOut);
			}
			
			for (var i=0;i<record.subdata.records.length;i++) {

				Ext.fly("subtable-" + records.records[i].id).on("mouseover", this.onMouseOver);
				Ext.fly("subtable-" + records.records[i].id).on("mouseout", this.onMouseOut);
			}
			
			
			
		});
		
	},
    renderer : function(v, p, record){
       	p.cellAttr = 'rowspan="2"';
       	return '<div class="x-grid3-row-expander"> </div>';
    },
	createSubdata: function () {
		
		switch (this.reader) {
			case "array":
				var reader = new Ext.data.ArrayReader({}, this.grid.store.reader.recordType);
				break;
			case "json":
			default:
				var reader = new Ext.data.JsonReader({}, this.grid.store.reader.recordType);
				break;
		}
		
		for (j=0;j<this.grid.getStore().getCount();j++) {
			var record = this.grid.getStore().getAt(j);

			if (record.data[this.subdata] && record.data[this.subdata].length > 0) {
				record.subdata = this.processRenderMethod(reader.readRecords(record.data[this.subdata]));
			} else {
				record.subdata = {};
				record.subdata.records = new Array();
			}
		}
	},
	doWidth: function () {
		this.reconfigureTemplate();
		this.updateRows();
	},
	onDblClick : function(e){
		var t = e.target;

		if (Ext.fly(t.id)) {
			var target = Ext.fly(t.id);
			if (target.hasClass("x-grid3-cell-subtablerow")) {
				
				var parent = target.findParent("tr.x-grid3-subtable-outertable-row", 10);
				
				var parent2 = target.findParent(this.grid.view.rowSelector, 20);
				var record = this.grid.store.getAt(parent2.rowIndex).subdata.records[parent.rowIndex];

				this.fireEvent("subdblclick", record);
			}
		}
    },
	onMouseOver: function (e) {
		var t = e.target;

		if (Ext.fly(t.id)) {
			var target = Ext.fly(t.id);
			if (target.hasClass("x-grid3-cell-subtablerow")) {

				var parent = target.findParent("table.x-grid3-row-subtable", 10, true);
				parent.addClass("x-grid3-row-over");
			}
		}
	},
	onMouseOut: function (e) {
		var t = e.target;

		if (Ext.fly(t.id)) {
			var target = Ext.fly(t.id);
			if (target.hasClass("x-grid3-cell-subtablerow")) {
				var parent = target.findParent("table.x-grid3-row-subtable", 10, true);
				parent.removeClass("x-grid3-row-over");

			}
		}
	},
	fly : function(el){
        if(!this._flyweight){
            this._flyweight = new Ext.Element.Flyweight(document.body);
        }
        this._flyweight.dom = el;
        return this._flyweight;
    },
	updateRow: function (row) {
		var record = this.grid.store.getAt(row);

	    if(typeof row == 'number'){
	        row = this.grid.view.getRow(row);
	    }
	    
	    var body = Ext.DomQuery.selectNode('tr:nth(2) div.x-grid3-row-body', row);
		
		records = record.subdata;

		var content = this.tpl.apply(records.records);
		
		this.bodyContent[record.id] = content;
	   	body.innerHTML = content;
		
	},
	updateRows: function () {
      	var ns = this.grid.view.getRows();
        for(var i = 0, len = ns.length; i < len; i++){
			this.updateRow(i);
		}
	},
	doAllWidths: function () {
		this.reconfigureTemplate();
		this.updateRows();
	},	
	getActivatedGridColumns: function () {
		var cm = this.grid.getColumnModel();
		
		var cols = [];
		
		
		
		for(var i = 0; i < cm.getColumnCount(); i++){
			if (!cm.isHidden(i)) {
				var col = {};
				var name = cm.getDataIndex(i);
				col.name = (typeof name == 'undefined' ? this.ds.fields.get(i).name : name);
				col.index = i;
				col.width = this.getColumnWidth(i);
				col.renderer = cm.getRenderer(i);
				cols.push(col);
			}
		}
		
		return cols;
	},
	getColumnWidth : function(col){
		var cm = this.grid.getColumnModel();
		
        var w = cm.getColumnWidth(col);
        if(typeof w == 'number'){
            w = (Ext.isBorderBox ? w : (w-this.grid.view.borderWidth > 0 ? w-this.grid.view.borderWidth:0));
        }
		
        return w;
    },
		
	reconfigureTemplate: function () {
		var cols = this.getActivatedGridColumns();

		var template = [
							'<table class="x-grid3-subtable-outertable" cellspacing="0">',
							'<tpl for=".">'
						];

		
		
		var padding, colWidth;
		
		template.push('<tr class="x-grid3-subtable-outertable-row"><td><table cellspacing="0" id="subtable-{values.id}" cellpadding="0" class="x-grid3-row-subtable"><tr class="x-grid3-row x-grid3-subtable-row-alt">');
		
		for(var i = 1; i < cols.length; i++){
			
			
			if (i == 1) {
				padding = '';
			} else {
				padding = '';
			}
		
			colWidth = cols[i].width;
			template.push('<td class="x-grid3-col x-grid3-cell x-grid3-td-'+cols[i].name+'" style="width: '+colWidth+'px;"><div style="'+padding+'" unselectable="on" id="subfield-{values.id}-'+cols[i].name+'" class="x-grid3-cell-subtablerow x-grid3-cell-inner x-grid3-col-'+cols[i].name+'">' + '{values.data.' + cols[i].name + '}</div></td>');
		}
		
		template.push('</tr>');
		template.push('</table></td></tr></tpl></table>');
		
		this.tpl = new Ext.XTemplate(template);
					
	    if(this.tpl){
	        if(typeof this.tpl == 'string'){
	            this.tpl = new Ext.Template(this.tpl);
	        }
	        this.tpl.compile();
	    }
				
		return;
		
	},
	processRenderMethod: function (records) {
		var cols = this.getActivatedGridColumns();

		for (var i=0;i<records.records.length;i++) {
			for(var j = 1; j< cols.length; j++){
				records.records[i].data[cols[j].name] = cols[j].renderer(records.records[i].data[cols[j].name],
																		 {},
																		 records.records[i]);
			}
		}
		
		return records;
	},
    getBodyContent : function(record, index){
		records = record.subdata;
		
		var body = "";
				
		if (records.records.length > 0) {
			body = this.tpl.apply(records.records);
		}
		this.bodyContent[record.id] = body;
		
		return body;
    }
});

/**
 * build form window
 */
//constructor
Ext.ux.FormWindow = function(config) {
  Ext.apply(this, config);
  Ext.ux.FormWindow.superclass.constructor.call(this);
}; 

// extend
Ext.extend(Ext.ux.FormWindow, Ext.Window, {
  monitorValid:false,
  monitorPoll:200,

  // private
  initComponent :function(){
      Ext.ux.FormWindow.superclass.initComponent.call(this);

      this.addEvents(
          /**
           * @event clientvalidation
           * If the monitorValid config option is true, this event fires repetitively to notify of valid state
           * @param {Ext.form.FormPanel} this
           * @param {Boolean} valid true if the form has passed client-side validation
           */
          'clientvalidation'
      );
  },
  
  // private
  initEvents : function(){
      Ext.ux.FormWindow.superclass.initEvents.call(this);

      if(this.monitorValid){ // initialize after render
          this.startMonitoring();
      }
  },
  
  /**
   * Starts monitoring of the valid state of this form. Usually this is done by passing the config
   * option "monitorValid"
   */
  startMonitoring : function(){
      if(!this.bound){
          this.bound = true;
          Ext.TaskMgr.start({
              run : this.bindHandler,
              interval : this.monitorPoll || 200,
              scope: this
          });
      }
  },

  /**
   * Stops monitoring of the valid state of this form
   */
  stopMonitoring : function(){
      this.bound = false;
  },
  
  // private
  bindHandler : function(){
    if(!this.bound){
        return false; // stops binding
    }
    
    var valid = true;
    this.cascade(function(comp) {
      if (comp.form) {
        if (!comp.form.isValid()) {
          valid=false;
          return false;
        }
      }
    });
    
    if(this.buttons){
        for(var i = 0, len = this.buttons.length; i < len; i++){
            var btn = this.buttons[i];
            if(btn.formBind === true && btn.disabled === valid){
                btn.setDisabled(!valid);
            }
        }
    }
    
    this.fireEvent('clientvalidation', this, valid);
  }
});

// --- create chooser ---
// ChooserField
//
// 
// http://www.extjs.com/license.txt
//

// Configuration:
//    loadUrl : URL to load images with
//    urlParams : parameters for the URL (?name=value&name=value...)
//    dlgWidth : initial width of chooser dialog
//    dlgHeight : initial height of chooser dialog
/*
Ext.form.ChooserField = function(config){
    Ext.form.ChooserField.superclass.constructor.call(this, config);
};
*/

Ext.form.ChooserField = Ext.extend( Ext.form.TwinTriggerField,  {
    trigger1Class : 'x-form-clear-trigger',
    trigger2Class:'x-form-browse-trigger',
    defaultAutoCreate : {tag: "input", type: "text", size: "10", autocomplete: "off"},
    hideTrigger1:true,
	hasValue:false,

    initComponent : function(){
		
		// --- add clear trigger ---
		this.addEvents("clear");
						
        Ext.form.ChooserField.superclass.initComponent.call(this);
		
        this.on('change', function($thisfield, $newValue, $oldValue){
			if ($newValue != null && $newValue != "") {
				this.hasValue = true;
				if (this.triggers != null) {
					this.triggers[0].show();
				}
			}
        }, this);

    },

    // Get the current value of our text field.
    
    getValue : function(){
        return Ext.form.ChooserField.superclass.getValue.call(this) || "";
    },

    // Set the current value of our text field.
    
    setValue : function(text){
		var $oldValue = this.getValue();
        Ext.form.DateField.superclass.setValue.call(this, text);
		
		this.fireEvent("change",this, text, $oldValue);		
    },

    // Trigger button clicked, create and show chooser dialog.
    
    onTrigger2Click : function(){
      if(this.disabled){
        return;
      }
      if (!this.chooser) {
		  
		  // ---- add the chooser interface ----
		  Ext.log("没有定义选择器!");
	  } else {
		  
			try {
				Interface.ensureImplements(this.chooser, Vsg.Chooser);
				
				this.chooser.show(this, this.setField.createDelegate(this));
			} catch (e) {
				Ext.log("传入的对像没有实现接口 : " + e);
			}		  
		  
	  }
    },
	
    onTrigger1Click : function(){
		
		if (this.hasValue) {
			try {
				this.fireEvent("clear", this);
				this.triggers[0].hide();
				this.hasValue = false;
								
			} catch (ex) {
				Ext.log("fire 'clear' event error : " + ex)
			}
		}

    },
	

    // Callback from chooser, put the selected file name in our text field.
    
    setField : function(data) {
      this.setValue(data);
    },

    loadUrl : '',
    urlParams : '',
    dlgWidth : 600,
    dlgHeight : 400,
    chooser: null
});
Ext.reg('chooserfield', Ext.form.ChooserField);


/**
 * extend the radio group defined 
 */

Ext.form.RadioGroup.prototype.setValue = function($value) {
    var p=this.el.up('form');//restrict to the form if it is in a form
	if(!p)p=Ext.getBody();
	// --- use group id defined ---
	var target = p.child('input[name=' + escape(this.dataIndex) + '][value=' + $value + ']', true);
	if (target && !target.checked) {
		Ext.getCmp(target.id).toggleValue();
	}
}
/*
Ext.form.RadioGroup.prototype.initValue = function($value){
	
}
*/